package fun.util.daohelper.hibernate;


import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

/*
 * Author: bin
 * Date: Jan 9, 2006
 * Time: 10:28:36 PM
 *
 * stolen from: http://www.hibernate.org/272.html
 */
public class EnumUserType implements UserType {

    private static final int[] SQL_TYPES = {Types.VARCHAR};

    public EnumUserType() {
        super();
    }

    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    public Class returnedClass() {
        return Enum.class;
    }

    public boolean equals(Object obj1, Object obj2) throws
            HibernateException {
        if (obj1 == obj2)
            return true;
        if (obj1 == null || obj2 == null)
            return false;
        return obj1.equals(obj2);
    }

    public int hashCode(Object object) throws HibernateException {
        return object.hashCode();
    }

    private String getRepresentation(Object object) {
        return object.getClass().getName() + " " + ((Enum) object).name();
    }

    private Object getObject(String representation) throws
            HibernateException {
        try {
            String[] parts = representation.split(" ");
            Class c = Class.forName(parts[0]);
            Field field = c.getField(parts[1]);
            return field.get(null);
        }
        catch (Exception e) {
            throw new HibernateException(e);
        }
    }

    public Object nullSafeGet(ResultSet resultSet, String[] names,
                              Object owner)
            throws HibernateException, SQLException {
        //if (resultSet.wasNull())
        //    return null;
        String value = resultSet.getString(names[0]);
        if ( value == null ) {
            return null;
        }
        return getObject(value);
    }

    public void nullSafeSet(PreparedStatement statement, Object value,
                            int index)
            throws HibernateException, SQLException {
        if (value == null)
            statement.setNull(index, Types.VARCHAR);
        else {
            String representation = getRepresentation(value);
            statement.setString(index, representation);
        }
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public boolean isMutable() {
        return false;
    }

    public Serializable disassemble(Object object) throws HibernateException {
        return getRepresentation(object);
    }

    public Object assemble(Serializable serializable, Object owner)
            throws HibernateException {
        return getObject((String) serializable);
    }

    public Object replace(Object original, Object target, Object owner)
            throws HibernateException {
        return original;
    }

}
